/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @file  SchM_Base.c
 * @brief Semidrive. AUTOSAR 4.3.1 MCAL Rte Emulation
 */


#if defined(CFG_NOT_USED_AUTOSAR_OS)
#include "SchM_Base.h"
#include <arch_irq.h>
#include "OsIf.h"

#define RTE_START_SEC_VAR_NO_INIT_NO_CACHE_UNSPECIFIED
#include "Rte_MemMap.h"
static volatile  uint32 Critical_NestedCount[8];
static volatile  uint32 Critical_SavedCPSRValue[8];

#if defined(ENABLE_CSA_TEST) /* only for test */
#define MAX_NEXT_DEEP   (16u)
#include "Mcal_Delay.h"
#include "debug.h"
static uint32  entry_point[8],exit_point[8];
/* only 32bit unsigned type can use */
#define ABS_DIFF_CYCLE(a,b)   ((uint32)(((uint32)(a))-((uint32)(b))))
#endif


#define RTE_STOP_SEC_VAR_NO_INIT_NO_CACHE_UNSPECIFIED
#include "Rte_MemMap.h"

#define RTE_START_SEC_CODE
#include "Rte_MemMap.h"

FUNC(void, RTE_CODE) SchM_EXCLUSIVE_AREA_INIT(void)
{
    uint8 coreid = 0;
#if defined(CFG_MULTI_CORE_SMP)
    coreid = OsIf_GetCoreID();
#endif /** #if defined(CFG_MULTI_CORE_SMP) */
    Critical_NestedCount[coreid] = 0;
}

/**
 * @brief Enter/Exit routines for Critical Area.
 */
FUNC(void, RTE_CODE) SchM_Enter_EXCLUSIVE_AREA(void)
{
    uint8 coreid = 0;
#if defined(CFG_MULTI_CORE_SMP)
    coreid = OsIf_GetCoreID();
#endif /** #if defined(CFG_MULTI_CORE_SMP) */
    uint32 cpsr = arch_irq_save();
    Critical_NestedCount[coreid]++;
    if (Critical_NestedCount[coreid] == 1U){
        Critical_SavedCPSRValue[coreid] = cpsr;
#if defined(ENABLE_CSA_TEST)
        entry_point[coreid] = read_pmccntr();
#endif
    }
}
/**
 * @brief Enter/Exit routines for Critical Area.
 */
FUNC(void, RTE_CODE) SchM_Exit_EXCLUSIVE_AREA(void)
{
    uint8 coreid = 0;
#if defined(CFG_MULTI_CORE_SMP)
    coreid = OsIf_GetCoreID();
#endif /** #if defined(CFG_MULTI_CORE_SMP) */
    arch_irq_disable();
    if(Critical_NestedCount[coreid]){
        Critical_NestedCount[coreid]--;
        if(Critical_NestedCount[coreid] == 0U){
#if defined(ENABLE_CSA_TEST)
            exit_point[coreid] = read_pmccntr();
            uint32 time_diff = ABS_DIFF_CYCLE(exit_point[coreid],entry_point[coreid]);
#endif
            if(!prev_irq_is_masked(Critical_SavedCPSRValue[coreid])){
                arch_irq_enable();
            }
#if defined(ENABLE_CSA_TEST)
            uint32 time = Mcal_TicksToUs(time_diff);
            if(time > 50)
            {
                PRINT("Oops:CSA too long (%dus)\n",time);
            }
#endif
        }
    }
}

#define RTE_STOP_SEC_CODE
#include "Rte_MemMap.h"

#endif
